package com.app.core.logger;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.time.Duration;
import java.time.LocalTime;
import java.util.Objects;

/**
 * @author qiangt
 * @version 1.0
 * @date 2023/10/19 14:50
 * @description: 记录日志到文件
 */
@Component
@Aspect
@Slf4j
@Order(9999)
public class LogAspect {

    private LocalTime time;

    /**
     * 打印参数
     */
    @Before("execution(* com.app..*.controller..*.*(..))" +
            "||execution(* com.app..*.service..*.*(..))" +
            "||execution(* com.app..*.cache..*.*(..))" +
            "||execution(* com.app..*.feign..*.*(..))" +
            "||execution(* com.app..*.api..*.*(..))" +
            "||execution(* com.app..*.manager..*.*(..))" +
            "||execution(* com.app..*.repository..*.*(..))")
    public void before(final JoinPoint joinPoint) {
        if (log.isInfoEnabled()) {
            // log.info("{} => {}", joinPoint, AopUtil.getParams(joinPoint));
        }
    }

    @Pointcut("execution(* com.app..*.controller..*.*(..))")
    public void point() {
    }

    @Before(value = "point()")
    public void before() {
        this.time = LocalTime.now();
    }

    /**
     * 打印执行时间和响应结果
     */
    @AfterReturning(value = "point()", returning = "result")
    public void afterReturn(final JoinPoint joinPoint, final Object result) {
        if (result instanceof SseEmitter) {
            log.info("SseEmitter");
            return;
        }
        if (log.isInfoEnabled()) {
            log.info("url: {} => time: {} ms({}-{})", this.getPath(), Duration.between(this.time, LocalTime.now()).toMillis(), this.time, LocalTime.now());
        }
        if (log.isDebugEnabled()) {
            log.info("response: {}", Objects.isNull(result) ? "" : JSON.toJSONString(result));
        }
    }

    /**
     * 获得请求URL
     *
     * @return String
     */
    private String getPath() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getRequestURI();
        } catch (final Exception e) {
            log.error(e.getMessage(), e);
            return "请求 URL 获取失败";
        }
    }
}
